package net.aiion.weave.spi.bytecode;

import java.util.Collection;

import net.aiion.weave.asm.Label;
import net.aiion.weave.asm.Type;
import net.aiion.weave.spi.bytecode.events.BytecodeEvent;

public interface BytecodeGenerator extends BytecodeSource
{
    void startClass(int aModifiers, String aName, String aSuperName, String... aInterfaceNames);
    
    void startClass(int aModifiers, String aName, Class<?> aSuperClass, Class<?>... aInterfaces);

    void startClass(int aModifiers, String aName, String aSignature, String aSuperName, String... aInterfaceNames);
    
    void startClass(int aModifiers, String aName, String aSignature, Class<?> aSuperClass, Class<?>... aInterfaces);

    void referenceInnerClass(String aInnerName, String aOuterName, String aInnerSimpleName, int aModifiers);

    void startField(int aModifiers, String aName, String aDescriptor);

    void startField(int aModifiers, String aName, Class<?> aType);

    void startField(int aModifiers, String aName, String aDescriptor, String aSignature, Object aConstantValue);

    void endField();

    void startMethod(int aModifiers, String aName, String aDescriptor);

    void startMethod(int aModifiers, String aName, String aReturnType, String... aParameterTypes);

    void startMethod(int aModifiers, String aName, Class<?> aReturnType, Class<?>... aParameterTypes);

    void startMethod(int aModifiers, String aName, String aDescriptor, String aSignature, String[] aExceptionNames);

    void startCode();

    void doNothing();

    void instanceOf(String aTypeName);

    void instanceOf(Type aType);

    void instanceOf(Class<?> aType);

    void invokeStatic(String aOwnerName, String aMethodName, String aMethodDescriptor);

    void invokeStatic(String aOwnerName, String aMethodName, String aReturnType, String... aParameterTypes);

    void invokeStatic(String aOwnerName, String aMethodName, Class<?> aReturnType, Class<?>... aParameterTypes);

    void invokeStatic(Class<?> aOwnerClass, String aMethodName, Class<?> aReturnType, Class<?>... aParameterTypes);

    void invokeConstructor(String aOwnerName, String aConstructorDescriptor);

    void invokeConstructor(String aOwnerName, String... aParameterTypes);

    void invokeConstructor(String aOwnerName, Class<?>... aParameterTypes);

    void invokeConstructor(Class<?> aOwnerClass, Class<?>... aParameterTypes);

    void invokeSpecial(String aOwnerName, String aMethodName, String aMethodDescriptor);

    void invokeSpecial(String aOwnerName, String aMethodName, String aReturnType, String... aParameterTypes);

    void invokeSpecial(String aOwnerName, String aMethodName, Class<?> aReturnType, Class<?>... aParameterTypes);

    void invokeSpecial(Class<?> aOwnerClass, String aMethodName, Class<?> aReturnType, Class<?>... aParameterTypes);

    void invokeInterface(String aOwnerName, String aMethodName, String aMethodDescriptor);

    void invokeInterface(String aOwnerName, String aMethodName, String aReturnType, String... aParameterTypes);

    void invokeInterface(String aOwnerName, String aMethodName, Class<?> aReturnType, Class<?>... aParameterTypes);

    void invokeInterface(Class<?> aOwnerClass, String aMethodName, Class<?> aReturnType, Class<?>... aParameterTypes);

    void invokeVirtual(String aOwnerName, String aMethodName, String aMethodDescriptor);

    void invokeVirtual(String aOwnerName, String aMethodName, String aReturnType, String... aParameterTypes);

    void invokeVirtual(String aOwnerName, String aMethodName, Class<?> aReturnType, Class<?>... aParameterTypes);

    void invokeVirtual(Class<?> aOwnerClass, String aMethodName, Class<?> aReturnType, Class<?>... aParameterTypes);

    void newReference(String aTypeName);

    void newReference(Class<?> aType);

    void newReferenceArray(String aComponentTypeName);

    void newReferenceArray(Class<?> aComponentTypeName);

    void duplicateReference();

    void pushNull();

    void pushConstant(Object aConstant);

    void pushConstant(Class<?> aType);

    void pushBoolean(boolean aBoolean);

    void pushInteger(int aInteger);

    void loadVariable(int aLocalVariableIndex, Type aLocalVariableType);

    void loadInteger(int aLocalVariableIndex);

    void loadReference(int aLocalVariableIndex);

    void loadReferenceArray(int aArrayIndex);

    void loadStatic(String aOwnerName, String aFieldName, String aFieldDescriptor);

    void loadStatic(String aOwnerName, String aFieldName, Class<?> aFieldType);

    void loadStatic(Class<?> aOwnerClass, String aFieldName, Class<?> aFieldType);

    void loadField(String aOwnerName, String aFieldName, String aFieldDescriptor);

    void loadField(String aOwnerName, String aFieldName, Class<?> aFieldType);

    void loadField(Class<?> aOwnerClass, String aFieldName, Class<?> aFieldType);

    void storeInteger(int aLocalVariableIndex);

    void storeReference(int aLocalVariableIndex);

    void storeReferenceArray();

    void storeField(String aOwnerName, String aFieldName, String aFieldDescriptor);

    void storeField(String aOwnerName, String aFieldName, Class<?> aFieldType);

    void storeField(Class<?> aOwnerClass, String aFieldName, Class<?> aFieldType);

    void popReference();

    void castChecked(String aTypeName);

    void castChecked(Type aType);

    void castChecked(Class<?> aType);

    void incrementInteger(int aLocalVariableIndex);

    void invokeValueOf(Type aType);

    void returnVoid();

    void returnVariable(Type aReturnType);

    void returnReference();

    void returnReference(Type aReturnType);

    void throwReference();

    void markLabel(Label aLabel);

    void markTryCatchBlock(Label aStartLabel, Label aEndLabel, Label aHandlerLabel, String aExceptionTypeName);

    void gotoLabel(Label aLabel);

    void jumpNull(Label aLabel);

    void jumpNotNull(Label aLabel);

    void jumpEquals(Label aLabel);

    void jumpNotEquals(Label aLabel);

    void jumpIntegerLessThan(Label aLabel);

    void markFrameSame();

    void markFrameAppend(int aLocalVariables, Object[] aLocalVariableTypes, int aStackElements,
        Object[] aStackElementTypes);

    void markFrameSame1(int aLocalVariables, Object[] aLocalVariableTypes, int aStackElements,
        Object[] aStackElementTypes);

    void markFrameChop(int aLocalVariables, Object[] aLocalVariableTypes, int aStackElements,
        Object[] aStackElementTypes);

    void markFrameFull(int aLocalVariables, Object[] aLocalVariableTypes, int aStackElements,
        Object[] aStackElementTypes);

    void endCode(int aMaximumStackSize, int aMaximumLocalVariables);

    void endMethod();

    void endClass();

    void dispatchBytecodeEvent(BytecodeEvent aBytecodeEvent);

    void dispatchBytecodeEvents(Collection<BytecodeEvent> aBytecodeEvents);
}
